home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 …ember: Reference Library / Dev.CD Dec 96 RL / Dev.CD Dec 96 RL.toast / Technical Documentation / develop / develop Issue 24 / develop Issue 24 code / Scriptable Database 1.0a15.sea / Scriptable Database 1.0a15 / Scripting / TransactionSuite.cp / TransactionSuite.cp
Encoding:
Text File  |  1996-02-20  |  11.8 KB  |  308 lines  |  [TEXT/CWIE]

  1.  
  2. #include "TransactionSuite.h"
  3. #include "Transaction.h"
  4. #include "MoreAEM.h"
  5. #include "EventHandlerTable.h"
  6.  
  7.  
  8.  
  9.  
  10. TTransactionList TTransactionSuite::gTransactionList;    
  11. long TTransactionSuite::gTransactionID = 1;
  12.  
  13. //----------------------------------------------------------------------------------------
  14. // TTransactionSuite::InstallAEHandlers: 
  15. //----------------------------------------------------------------------------------------
  16. void TTransactionSuite::InstallAEHandlers(TEventHandlerTable& eventTable)
  17. {    
  18.     //
  19.     // The event handler table will create a UPP if it needs to
  20.     //
  21.     FailErr(eventTable.InstallHandler(kAEMiscStandards, kAEBeginTransaction, (EventHandlerProcPtr) &TTransactionSuite::BeginTransaction, 0));
  22.     FailErr(eventTable.InstallHandler(kAEMiscStandards, kAEEndTransaction, (EventHandlerProcPtr) &TTransactionSuite::EndTransaction, 0));
  23.     FailErr(eventTable.InstallHandler(kAEMiscStandards, kAETransactionTerminated, (EventHandlerProcPtr) &TTransactionSuite::TerminateTransaction, 0));
  24. } // TCoreSuite::InstallAEHandlers 
  25.  
  26. //----------------------------------------------------------------------------------------
  27. // TTransactionSuite::GenerateNewTransactionID
  28. //----------------------------------------------------------------------------------------
  29. SInt32 TTransactionSuite::GenerateNewTransactionID()
  30. {
  31.     return ++gTransactionID;
  32. }
  33.  
  34. //----------------------------------------------------------------------------------------
  35. // TTransactionSuite::BeginTransaction: 
  36. //
  37. // This event is received at the beginning of a new transaction.
  38. //----------------------------------------------------------------------------------------
  39. pascal OSErr TTransactionSuite::BeginTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
  40. {
  41.     // DebugStr("\pTTransactionSuite::BeginTransaction");
  42.     TAETransaction t(ae, reply);
  43.     OSErr err = noErr;
  44.     
  45.     //
  46.     // AppleScript inserts a parameter keySubjectAttr in the
  47.     // transaction, but I'm not sure how to specify what data
  48.     // it should contain (it's a null descriptor by default).
  49.     // If you say:
  50.     //
  51.     //        with transaction "some text"
  52.     //
  53.     // then "some text" will be in the direct object of the
  54.     // transaction; of course, other data types (e.g. object
  55.     // specifiers) could be used here as well, and might be
  56.     // useful for some types of transactions.
  57.     //
  58.     // It might be useful to associate the subject of the
  59.     // transaction with the transaction object so that it
  60.     // (the subject) may be returned along with the error
  61.     // code when an event fails due to a conflict with some
  62.     // other transaction.
  63.     //
  64.     
  65.     //
  66.     // We don't expect that there will be a transaction associated
  67.     // with this event, but we'll test for it anyway
  68.     //
  69.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  70.     if(transaction == nil)
  71.     {
  72.         long transactionID = TTransactionSuite::GenerateNewTransactionID();
  73.         TTransactionSuite::BeginEventTransaction(t, kMultiEventTransaction, transactionID, true);
  74.         
  75.         //
  76.         // Put the transaction ID into the result and also a 'keyTransactionIDAttr'
  77.         // (AppleScript looks at this parameter--not attribute--in the reply)
  78.         //
  79.         reply.PutSInt32Parameter(keyTransactionIDAttr, transactionID);    
  80.         reply.PutSInt32Parameter(keyAEResult, transactionID);    
  81.     }
  82.     
  83.     return err;
  84. }
  85.  
  86.  
  87. //----------------------------------------------------------------------------------------
  88. // TTransactionSuite::EndTransaction: 
  89. //
  90. // This event is received at the end of a successful transaction
  91. //----------------------------------------------------------------------------------------
  92. pascal OSErr TTransactionSuite::EndTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
  93. {
  94.     // DebugStr("\pTTransactionSuite::EndTransaction");
  95.     TAETransaction t(ae, reply);
  96.     OSErr err = noErr;
  97.     
  98.     //
  99.     // Get the transaction from the event and commit its changes.
  100.     //
  101.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  102.     if(transaction != nil)
  103.     {
  104.         TTransactionSuite::EndEventTransaction(t, true);
  105.     }
  106.  
  107.     return err;
  108. }
  109.  
  110. //----------------------------------------------------------------------------------------
  111. // TTransactionSuite::TerminateTransaction: 
  112. //
  113. // This event is received when a transaction is aborted due to some failure
  114. //----------------------------------------------------------------------------------------
  115. pascal OSErr TTransactionSuite::TerminateTransaction(TAEvent& ae, TAEvent& reply, long /* refCon */)
  116. {
  117.     // DebugStr("\pTTransactionSuite::TerminateTransaction");
  118.     TAETransaction t(ae, reply);
  119.     OSErr err = noErr;
  120.  
  121.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  122.     if(transaction != nil)
  123.     {
  124.         TTransactionSuite::TerminateEventTransaction(t, true);
  125.     }
  126.  
  127.     return err;
  128. }
  129.  
  130. //----------------------------------------------------------------------------------------
  131. // TTransactionSuite::GetTransactionFromEvent
  132. //
  133. // Look up the transaction associated with the current event.  Return nil if there
  134. // is no item in the list that matches the event's transaction ID.
  135. //----------------------------------------------------------------------------------------
  136. TTransaction* TTransactionSuite::GetTransactionFromEvent(const TAETransaction& t)
  137. {
  138.     TTransaction* transaction = (TTransaction*)t.TransactionCache();
  139.     if(transaction == nil)
  140.     {
  141.         transaction = gTransactionList.FindTransaction(t.GetTransactionID());
  142.         ((TAETransaction&)t).SetTransactionCache(transaction);
  143.     }
  144.     
  145.     return transaction;
  146. }
  147.  
  148. //----------------------------------------------------------------------------------------
  149. // TTransactionSuite::BeginEventTransaction
  150. //
  151. // An event handler calls this method to fetch the transaction associated with
  152. // the given AppleEvent.  If the AppleEvent is not part of any transaction, then
  153. // by default, a new transaction is created for the exclusive use of this event.
  154. // If the event handler does not require a transaction (if, for example, the event
  155. // never modifies the state of any transaction-controlled object), then it can
  156. // pass 'false' for transactionAlwaysNeeded to suppress creation of the temporary
  157. // transaction.
  158. //
  159. // n.b. Read-only event handlers should always use the transaction associated with
  160. // an event so that it can 'see' changes made by previous events in the same
  161. // transaction.
  162. //----------------------------------------------------------------------------------------
  163. void TTransactionSuite::BeginEventTransaction(TAETransaction& t, Boolean transactionAlwaysNeeded /*= true*/)
  164. {
  165.     BeginEventTransaction(t, kSingleEventTransaction, TTransactionSuite::GenerateNewTransactionID(), transactionAlwaysNeeded);
  166. }
  167.  
  168. //----------------------------------------------------------------------------------------
  169. // TTransactionSuite::BeginEventTransaction
  170. //
  171. // Protected version of above method; a transactionType of kMultiEventTransaction
  172. // can only be provided by the BeginTransaction event.
  173. //----------------------------------------------------------------------------------------
  174. void TTransactionSuite::BeginEventTransaction(TAETransaction& t, AETransactionType transactionType, SInt32 transactionID, Boolean transactionAlwaysNeeded /*= true*/)
  175. {
  176.     // DebugStr("\pTTransactionSuite::BeginEventTransaction");
  177.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  178.     
  179.     if((transaction == nil) && transactionAlwaysNeeded)
  180.     {
  181.         transaction = new TTransaction;
  182.         t.SetTransactionCache(transaction);
  183.         gTransactionList.AddTransaction(transaction, transactionID, transactionType);
  184.     }
  185. }
  186.  
  187. //----------------------------------------------------------------------------------------
  188. // TTransactionSuite::EndEventTransaction
  189. //
  190. // An event hander calls this method when it completes sucessfully.  If this event
  191. // is part of some transaction, then no action is taken at this time.  If the event
  192. // is being executed outside of any transaction, though, then the changes it affected
  193. // are committed and the transaction is deleted.
  194. //----------------------------------------------------------------------------------------
  195. void TTransactionSuite::EndEventTransaction(TAETransaction& t, Boolean alwaysDeleteTransaction)
  196. {
  197.     // DebugStr("\pTTransactionSuite::EndEventTransaction");
  198.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  199.     if(transaction != nil)
  200.     {
  201.         //
  202.         // If this event was not associated with any specific
  203.         // transaction, then there will never be an end
  204.         // transaction event--we'd better commit our changes
  205.         // and delete the transaction right now.
  206.         //
  207.         if((gTransactionList.TransactionType(transaction) == kSingleEventTransaction) || (alwaysDeleteTransaction == true))
  208.         {
  209.             // DebugStr("\pCommit changes and delete transaction");
  210.             transaction->CommitChanges();
  211.             gTransactionList.RemoveTransaction(transaction);
  212.             delete transaction;
  213.             t.SetTransactionCache(nil);
  214.         }
  215.     }
  216. }
  217.  
  218. //----------------------------------------------------------------------------------------
  219. // TTransactionSuite::TerminateEventTransaction
  220. //
  221. // An event handler calls this method if the event failed for some reason.
  222. // This method will back out all changes and delete the transaction, if necessary.
  223. //----------------------------------------------------------------------------------------
  224. void TTransactionSuite::TerminateEventTransaction(TAETransaction& t, Boolean alwaysDeleteTransaction)
  225. {
  226.     // DebugStr("\pTTransactionSuite::TerminateEventTransaction");
  227.     TTransaction* transaction = TTransactionSuite::GetTransactionFromEvent(t);
  228.     if(transaction != nil)
  229.     {
  230.         //
  231.         // Always discard our changes up to now, even if we're in the
  232.         // middle of a transaction.  We don't expect to get any more
  233.         // events in this transaction, but if we do, we will begin
  234.         // making changes again from the beginning.
  235.         //
  236.         // If we aren't in a transaction, then we'd better delete the
  237.         // transaction object right now.
  238.         //
  239.         transaction->DiscardChanges();
  240.         if((gTransactionList.TransactionType(transaction) == kSingleEventTransaction) || (alwaysDeleteTransaction == true))
  241.         {
  242.             gTransactionList.RemoveTransaction(transaction);
  243.             delete transaction;
  244.             t.SetTransactionCache(nil);
  245.         }
  246.     }
  247. }
  248.  
  249.  
  250.  
  251. //----------------------------------------------------------------------------------------
  252. // TTransactionList::AddTransaction
  253. //----------------------------------------------------------------------------------------
  254. void TTransactionList::AddTransaction(TTransaction* t, long transactionID, AETransactionType transactionType)
  255. {
  256.     fTransactionList.InsertAtEnd(TTransactionRecord(t, transactionID, transactionType));
  257. }
  258.  
  259. //----------------------------------------------------------------------------------------
  260. // TTransactionList::FindTransaction
  261. //----------------------------------------------------------------------------------------
  262. TTransaction* TTransactionList::FindTransaction(long transactionID) const
  263. {
  264.     TTransaction* t = nil;
  265.     for(AnIteratorOfAListOf<TTransactionRecord> iter((AListOf<TTransactionRecord>*)&fTransactionList); iter.More(); iter.Next())
  266.     {
  267.         if(iter.Current().TransactionID() == transactionID)
  268.         {
  269.             t = iter.Current().Transaction();
  270.             break;
  271.         }
  272.     }
  273.     
  274.     return t;
  275. }
  276.  
  277. //----------------------------------------------------------------------------------------
  278. // TTransactionList::RemoveTransaction
  279. //----------------------------------------------------------------------------------------
  280. void TTransactionList::RemoveTransaction(TTransaction* transaction)
  281. {
  282.     for(AnIteratorOfAListOf<TTransactionRecord> iter(&fTransactionList); iter.More(); iter.Next())
  283.     {
  284.         if(iter.Current().Transaction() == transaction)
  285.         {
  286.             iter.RemoveCurrent();
  287.         }
  288.     }
  289. }
  290.  
  291. //----------------------------------------------------------------------------------------
  292. // TTransactionList::TransactionType
  293. //----------------------------------------------------------------------------------------
  294. AETransactionType TTransactionList::TransactionType(TTransaction* transaction) const
  295. {
  296.     AETransactionType t = kNoSuchTransaction;
  297.     for(AnIteratorOfAListOf<TTransactionRecord> iter((AListOf<TTransactionRecord>*)&fTransactionList); iter.More(); iter.Next())
  298.     {
  299.         if(iter.Current().Transaction() == transaction)
  300.         {
  301.             t = iter.Current().TransactionType();
  302.             break;
  303.         }
  304.     }
  305.     
  306.     return t;
  307. }
  308.